package com.fj.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Set;

/**
 * @author fj
 * @date 2023/12/12 09:31
 */
public class GroupChatServer {
    private ServerSocketChannel serverSocketChannel;
    private Selector selector;

    public GroupChatServer(int port) {
        try {
            this.serverSocketChannel = ServerSocketChannel.open();
            this.selector = Selector.open();
            this.serverSocketChannel.socket().bind(new InetSocketAddress(port));
            this.serverSocketChannel.configureBlocking(false);
            this.serverSocketChannel.register(this.selector, SelectionKey.OP_ACCEPT);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public void listen() throws IOException {
        System.out.println("启动完成，开始监听...");
        while (true) {
            selector.select(1000);
            Set<SelectionKey> selectionKeys = selector.selectedKeys();
            Iterator<SelectionKey> iterator = selectionKeys.iterator();
            while (iterator.hasNext()) {
                SelectionKey selectionKey = iterator.next();
                //获取当前在线客户端
                if (selectionKey.isAcceptable()) {
                    SocketChannel socketChannel = serverSocketChannel.accept();
                    System.out.println(socketChannel.getRemoteAddress() + "上线了");
                    socketChannel.configureBlocking(false);
                    socketChannel.register(selector, SelectionKey.OP_READ);
                }
                if (selectionKey.isReadable()) {
                    SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
                    SocketAddress remoteAddress = socketChannel.getRemoteAddress();
                    ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
                    int read = socketChannel.read(byteBuffer);
                    if (read > 0) {
                        String msg = new String(byteBuffer.array());
                        String from = remoteAddress.toString();
                        System.out.println(from + "发送了一条消息");
                        broadCast(from, msg, socketChannel);
                    }
                }
                //处理完移除事件迭代器，避免重复处理时间
                iterator.remove();
            }

        }
    }

    private void broadCast(String from, String msg, Channel current) {
        Set<SelectionKey> keys = selector.keys();
        Iterator<SelectionKey> iterator = keys.iterator();
        while (iterator.hasNext()) {
            SelectionKey selectionKey = iterator.next();
            if (selectionKey.channel() instanceof SocketChannel && current != selectionKey.channel()) {
                System.out.println("转发");
                //跳过服务器自身channel
                SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
                try {
                    socketChannel.write(ByteBuffer.wrap((from + ":" + msg).getBytes()));
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }

    public static void main(String[] args) throws IOException {
        GroupChatServer groupChatServer = new GroupChatServer(6789);
        groupChatServer.listen();
    }
}
